home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / program / gcc / ixemul-4.lha / ixemul-41.4 / network / res_comp.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  8KB  |  350 lines

  1. /*
  2.  * Copyright (c) 1985 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)res_comp.c    6.22 (Berkeley) 3/19/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <arpa/nameser.h>
  40. #include <netinet/in.h>
  41. #include <resolv.h>
  42. #include <stdio.h>
  43.  
  44. static dn_find();
  45.  
  46. /*
  47.  * Expand compressed domain name 'comp_dn' to full domain name.
  48.  * 'msg' is a pointer to the begining of the message,
  49.  * 'eomorig' points to the first location after the message,
  50.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  51.  * Return size of compressed name or -1 if there was an error.
  52.  */
  53. dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  54.     const u_char *msg, *eomorig, *comp_dn;
  55.     u_char *exp_dn;
  56.     int length;
  57. {
  58.     register u_char *cp, *dn;
  59.     register int n, c;
  60.     u_char *eom;
  61.     int len = -1, checked = 0;
  62.  
  63.     dn = exp_dn;
  64.     cp = (u_char *)comp_dn;
  65.     eom = exp_dn + length;
  66.     /*
  67.      * fetch next label in domain name
  68.      */
  69.     while (n = *cp++) {
  70.         /*
  71.          * Check for indirection
  72.          */
  73.         switch (n & INDIR_MASK) {
  74.         case 0:
  75.             if (dn != exp_dn) {
  76.                 if (dn >= eom)
  77.                     return (-1);
  78.                 *dn++ = '.';
  79.             }
  80.             if (dn+n >= eom)
  81.                 return (-1);
  82.             checked += n + 1;
  83.             while (--n >= 0) {
  84.                 if ((c = *cp++) == '.') {
  85.                     if (dn + n + 2 >= eom)
  86.                         return (-1);
  87.                     *dn++ = '\\';
  88.                 }
  89.                 *dn++ = c;
  90.                 if (cp >= eomorig)    /* out of range */
  91.                     return(-1);
  92.             }
  93.             break;
  94.  
  95.         case INDIR_MASK:
  96.             if (len < 0)
  97.                 len = cp - comp_dn + 1;
  98.             cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  99.             if (cp < msg || cp >= eomorig)    /* out of range */
  100.                 return(-1);
  101.             checked += 2;
  102.             /*
  103.              * Check for loops in the compressed name;
  104.              * if we've looked at the whole message,
  105.              * there must be a loop.
  106.              */
  107.             if (checked >= eomorig - msg)
  108.                 return (-1);
  109.             break;
  110.  
  111.         default:
  112.             return (-1);            /* flag error */
  113.         }
  114.     }
  115.     *dn = '\0';
  116.     if (len < 0)
  117.         len = cp - comp_dn;
  118.     return (len);
  119. }
  120.  
  121. /*
  122.  * Compress domain name 'exp_dn' into 'comp_dn'.
  123.  * Return the size of the compressed name or -1.
  124.  * 'length' is the size of the array pointed to by 'comp_dn'.
  125.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  126.  * is a pointer to the beginning of the message. The list ends with NULL.
  127.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  128.  * by 'dnptrs'. Side effect is to update the list of pointers for
  129.  * labels inserted into the message as we compress the name.
  130.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  131.  * is NULL, we don't update the list.
  132.  */
  133. dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  134.     const u_char *exp_dn;
  135.     u_char *comp_dn, **dnptrs, **lastdnptr;
  136.     int length;
  137. {
  138.     register u_char *cp, *dn;
  139.     register int c, l;
  140.     u_char **cpp, **lpp, *sp, *eob;
  141.     u_char *msg;
  142.  
  143.     dn = (u_char *)exp_dn;
  144.     cp = comp_dn;
  145.     eob = cp + length;
  146.     if (dnptrs != NULL) {
  147.         if ((msg = *dnptrs++) != NULL) {
  148.             for (cpp = dnptrs; *cpp != NULL; cpp++)
  149.                 ;
  150.             lpp = cpp;    /* end of list to search */
  151.         }
  152.     } else
  153.         msg = NULL;
  154.     for (c = *dn++; c != '\0'; ) {
  155.         /* look to see if we can use pointers */
  156.         if (msg != NULL) {
  157.             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  158.                 if (cp+1 >= eob)
  159.                     return (-1);
  160.                 *cp++ = (l >> 8) | INDIR_MASK;
  161.                 *cp++ = l % 256;
  162.                 return (cp - comp_dn);
  163.             }
  164.             /* not found, save it */
  165.             if (lastdnptr != NULL && cpp < lastdnptr-1) {
  166.                 *cpp++ = cp;
  167.                 *cpp = NULL;
  168.             }
  169.         }
  170.         sp = cp++;    /* save ptr to length byte */
  171.         do {
  172.             if (c == '.') {
  173.                 c = *dn++;
  174.                 break;
  175.             }
  176.             if (c == '\\') {
  177.                 if ((c = *dn++) == '\0')
  178.                     break;
  179.             }
  180.             if (cp >= eob) {
  181.                 if (msg != NULL)
  182.                     *lpp = NULL;
  183.                 return (-1);
  184.             }
  185.             *cp++ = c;
  186.         } while ((c = *dn++) != '\0');
  187.         /* catch trailing '.'s but not '..' */
  188.         if ((l = cp - sp - 1) == 0 && c == '\0') {
  189.             cp--;
  190.             break;
  191.         }
  192.         if (l <= 0 || l > MAXLABEL) {
  193.             if (msg != NULL)
  194.                 *lpp = NULL;
  195.             return (-1);
  196.         }
  197.         *sp = l;
  198.     }
  199.     if (cp >= eob) {
  200.         if (msg != NULL)
  201.             *lpp = NULL;
  202.         return (-1);
  203.     }
  204.     *cp++ = '\0';
  205.     return (cp - comp_dn);
  206. }
  207.  
  208. /*
  209.  * Skip over a compressed domain name. Return the size or -1.
  210.  */
  211. __dn_skipname(comp_dn, eom)
  212.     const u_char *comp_dn, *eom;
  213. {
  214.     register u_char *cp;
  215.     register int n;
  216.  
  217.     cp = (u_char *)comp_dn;
  218.     while (cp < eom && (n = *cp++)) {
  219.         /*
  220.          * check for indirection
  221.          */
  222.         switch (n & INDIR_MASK) {
  223.         case 0:        /* normal case, n == len */
  224.             cp += n;
  225.             continue;
  226.         default:    /* illegal type */
  227.             return (-1);
  228.         case INDIR_MASK:    /* indirection */
  229.             cp++;
  230.         }
  231.         break;
  232.     }
  233.     return (cp - comp_dn);
  234. }
  235.  
  236. /*
  237.  * Search for expanded name from a list of previously compressed names.
  238.  * Return the offset from msg if found or -1.
  239.  * dnptrs is the pointer to the first name on the list,
  240.  * not the pointer to the start of the message.
  241.  */
  242. static
  243. dn_find(exp_dn, msg, dnptrs, lastdnptr)
  244.     u_char *exp_dn, *msg;
  245.     u_char **dnptrs, **lastdnptr;
  246. {
  247.     register u_char *dn, *cp, **cpp;
  248.     register int n;
  249.     u_char *sp;
  250.  
  251.     for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  252.         dn = exp_dn;
  253.         sp = cp = *cpp;
  254.         while (n = *cp++) {
  255.             /*
  256.              * check for indirection
  257.              */
  258.             switch (n & INDIR_MASK) {
  259.             case 0:        /* normal case, n == len */
  260.                 while (--n >= 0) {
  261.                     if (*dn == '.')
  262.                         goto next;
  263.                     if (*dn == '\\')
  264.                         dn++;
  265.                     if (*dn++ != *cp++)
  266.                         goto next;
  267.                 }
  268.                 if ((n = *dn++) == '\0' && *cp == '\0')
  269.                     return (sp - msg);
  270.                 if (n == '.')
  271.                     continue;
  272.                 goto next;
  273.  
  274.             default:    /* illegal type */
  275.                 return (-1);
  276.  
  277.             case INDIR_MASK:    /* indirection */
  278.                 cp = msg + (((n & 0x3f) << 8) | *cp);
  279.             }
  280.         }
  281.         if (*dn == '\0')
  282.             return (sp - msg);
  283.     next:    ;
  284.     }
  285.     return (-1);
  286. }
  287.  
  288. /*
  289.  * Routines to insert/extract short/long's. Must account for byte
  290.  * order and non-alignment problems. This code at least has the
  291.  * advantage of being portable.
  292.  *
  293.  * used by sendmail.
  294.  */
  295.  
  296. u_short
  297. _getshort(msgp)
  298.     u_char *msgp;
  299. {
  300.     register u_char *p = (u_char *) msgp;
  301. #ifdef vax
  302.     /*
  303.      * vax compiler doesn't put shorts in registers
  304.      */
  305.     register u_long u;
  306. #else
  307.     register u_short u;
  308. #endif
  309.  
  310.     u = *p++ << 8;
  311.     return ((u_short)(u | *p));
  312. }
  313.  
  314. u_long
  315. _getlong(msgp)
  316.     u_char *msgp;
  317. {
  318.     register u_char *p = (u_char *) msgp;
  319.     register u_long u;
  320.  
  321.     u = *p++; u <<= 8;
  322.     u |= *p++; u <<= 8;
  323.     u |= *p++; u <<= 8;
  324.     return (u | *p);
  325. }
  326.  
  327. void
  328. #ifdef __STDC__
  329. __putshort(register u_short s, register u_char *msgp)
  330. #else
  331. __putshort(s, msgp)
  332.     register u_short s;
  333.     register u_char *msgp;
  334. #endif
  335. {
  336.     msgp[1] = s;
  337.     msgp[0] = s >> 8;
  338. }
  339.  
  340. void
  341. __putlong(l, msgp)
  342.     register u_long l;
  343.     register u_char *msgp;
  344. {
  345.     msgp[3] = l;
  346.     msgp[2] = (l >>= 8);
  347.     msgp[1] = (l >>= 8);
  348.     msgp[0] = l >> 8;
  349. }
  350.